home *** CD-ROM | disk | FTP | other *** search
/ Sounds Terrific 2 / Sounds Terrific II (1996)(Weird Science)(Disc 1 of 2)[Amiga-PC].iso / archives / amiga / amichord.lha / AmiChord / src / chord.c next >
C/C++ Source or Header  |  1995-04-09  |  25KB  |  782 lines

  1. #include "chord.h"
  2.  
  3. unsigned char versiontag[] = "\0$VER: AmiChord 1.2 (" __DATE__ ")";
  4.  
  5. FILE *source_fd;
  6. FILE *toc_file = NULL;          /* optional table of contents file */
  7.  
  8. unsigned char
  9.         text_line[MAXLINE],     /* Lyrics Buffer */
  10.         chord[MAXTOKEN],        /* Buffer for the name of the chord */
  11.         title1[MAXLINE];        /* Holds the first title line */
  12.  
  13. char
  14.         source[MAXTOKEN],
  15.         directive[MAXTOKEN],    /* Buffer for the directive */
  16.         mesg[MAXTOKEN];
  17.  
  18. char
  19.         i_input;                /* Input line pointer */
  20. char
  21.         *text_font = DEF_TEXT_FONT,     /* Default font for text */
  22.         *chord_font = DEF_CHORD_FONT,   /* Default font for chord */
  23.         *used_fonts[MAXFONTS][MAXLINE],
  24.         *current_file,
  25.         *chord_line[MAXLINE];
  26.  
  27. char *notes[7] =  { "C", "D", "E", "F", "G", "A", "B" };
  28.  
  29. int
  30.         c,                      /* Current character in input file */
  31.         i_chord,                /* Index to 'chord' */
  32.         i_directive,            /* Index to 'directive' */
  33.         i_text,                 /* Index to 'text_line' */
  34.         in_chord,               /* Booleans indicating parsing status */
  35.         lyrics_only = FALSE,
  36.         auto_space = FALSE,     /* applies lyrics_only when no chords */
  37.         left_foot_odd = -1,     /* -1 for all page numbers on the right */
  38.                                 /* 0 for odd page numbers on the right */
  39.                                 /* 1 for odd page numbers on the left */
  40.         number_all = FALSE,     /* number the first page (set with -p 1) */
  41.         page_label = 1,         /* page number for footers and index */
  42.         i_chord_ov,             /* Overflow Booleans */
  43.         i_directive_ov = FALSE,
  44.         i_text_ov = FALSE,
  45.         in_directive = FALSE,
  46.         in_chordrc = FALSE,
  47.         in_chorus = FALSE,
  48.         has_directive = FALSE,
  49.         has_chord = FALSE,
  50.         title1_found = FALSE,
  51.         debug_mode = FALSE,
  52.         need_soc = FALSE,
  53.         pagination = 1,         /* virtual pages per physical pages */
  54.         transpose = 0,          /* transposition value */
  55.         vpos,                   /* Current PostScript position, in points */
  56.         hpos,
  57.         start_of_chorus,        /* Vertical positions of the chorus */
  58.         end_of_chorus,
  59.         chord_size = DEF_CHORD_SIZE,    /* Default font size for 'chord_font' */
  60.         text_size = DEF_TEXT_SIZE,      /* Default font size for 'text_font' */
  61.         grid_size = DEF_GRID_SIZE,
  62.         n_pages = 1,            /* total page counter */
  63.         v_pages = 1,            /* virtual pages */
  64.         n_lines = 1,            /* line number in input file */
  65.         song_pages = 1,         /* song page counter */
  66.         blank_space = 0;        /* consecutive blank line counter */
  67.  
  68. float
  69.         chord_inc,
  70.         scale = 1.0,            /* Current scale factor */
  71.         rotation = 0.0;         /* Current rotation */
  72.  
  73. extern int nb_chord, first_ptr;
  74. extern struct chord_struct chordtab[MAX_CHORD];
  75.  
  76. extern char *optarg;
  77. extern int optind, opterr;
  78.  
  79. /* --------------------------------------------------------------------------------*/
  80. use_chord_font() {
  81.     printf ("CHORD_FONT setfont\n");
  82. }
  83.  
  84. /* --------------------------------------------------------------------------------*/
  85. set_chord_font() {
  86.     printf ("/CHORD_FONT { /%s findfont %d scalefont } def\n", chord_font, chord_size);
  87.     re_encode (chord_font);
  88. }
  89.  
  90. /* --------------------------------------------------------------------------------*/
  91. use_text_font() {
  92.     printf ("TEXT_FONT setfont\n");
  93. }
  94.  
  95. /* --------------------------------------------------------------------------------*/
  96. set_text_font (int size) {
  97.     printf ("/TEXT_FONT { /%s findfont %d scalefont } def\n", text_font, size);
  98.     re_encode (text_font);
  99. }
  100.  
  101. /* --------------------------------------------------------------------------------*/
  102. do_help (char *command) {
  103.     fprintf (stderr, "Usage: %s [options] file\n", command);
  104.     fprintf (stderr, "Options:\n");
  105.     fprintf (stderr, "      -c n               : set chord size [9]\n");
  106.     fprintf (stderr, "      -C postsctipt_font : Set chord font\n");
  107.     fprintf (stderr, "      -t n               : set text size [12]\n");
  108.     fprintf (stderr, "      -T postsctipt_font : set text font\n");
  109.     fprintf (stderr, "      -g n               : set chord grid size [30]\n");
  110.     fprintf (stderr, "      -l                 : only print lyrics\n");
  111.     fprintf (stderr, "      -h                 : This message\n");
  112.     fprintf (stderr, "      -2                 : 2 pages per sheet\n");
  113.     fprintf (stderr, "      -4                 : 4 pages per sheet\n");
  114.     fprintf (stderr, "      -d                 : dumps default chords definitions\n");
  115.     fprintf (stderr, "      -i file            : write table of contents to file\n");
  116.     fprintf (stderr, "      -a                 : automatic single space lines without chords\n");
  117.     fprintf (stderr, "      -p n               : starting page number [1]\n");
  118.     fprintf (stderr, "      -R                 : odd pages numbers on right\n");
  119.     fprintf (stderr, "      -L                 : odd pages numbers on left\n");
  120. }
  121.  
  122. /* --------------------------------------------------------------------------------*/
  123. do_chord (int i_text, char *chord) {
  124.     if (transpose != 0)
  125.         if (do_transpose (chord) != 0) {
  126.             sprintf (mesg, "Don't know how to transpose [%s]", chord);
  127.             error (mesg);
  128.     } if (i_text < MAXLINE)
  129.         chord_line[i_text] = chordtab[add_to_chordtab (chord)].chord_name;
  130. }
  131.  
  132. /* --------------------------------------------------------------------------------*/
  133. print_chord_line () {
  134.     int i, j;                   /* Counter */
  135.  
  136.     for (j = 0; j < MAXLINE; j++) {
  137.         if (chord_line[j] != NULL) {
  138.             use_text_font ();
  139.             printf ("(");
  140.             for (i = 0; i < j; printf ("%c", text_line[i++]));
  141.             printf (") stringwidth  pop %d add %d moveto\n", hpos, vpos);
  142.  
  143.             use_chord_font ();
  144.             printf ("(%s) show\n", chord_line[j]);
  145.  
  146.             chord_line[j] = NULL;
  147.         }
  148.     }
  149. }
  150.  
  151. /* --------------------------------------------------------------------------------*/
  152. do_directive (char *directive) {
  153.     int i;
  154.     char *command, *comment;
  155.  
  156.     command = (char *) strtok (directive, ": ");
  157.  
  158.     if (!strcmp (command, "start_of_chorus") || !strcmp (command, "soc")) {
  159.         /* start_of_chorus = vpos - blank_space; */
  160.         need_soc = TRUE;
  161.         in_chorus = TRUE;
  162.     }
  163.     else if (!strcmp (command, "end_of_chorus") || !strcmp (command, "eoc")) {
  164.         if (in_chorus) {
  165.             end_of_chorus = vpos;
  166.             do_chorus_line ();
  167.             in_chorus = FALSE;
  168.         }
  169.         else
  170.             error ("Not in a chorus.");
  171.     }
  172.     else if (!strcmp (command, "textfont") || !strcmp (command, "tf")) {
  173.         text_font = (char *) strtok (NULL, ": ");
  174.     }
  175.     else if (!strcmp (command, "chordfont") || !strcmp (command, "cf")) {
  176.         chord_font = (char *) strtok (NULL, ": ");
  177.         set_chord_font ();
  178.     }
  179.     else if (!strcmp (command, "chordsize") || !strcmp (command, "cs")) {
  180.         i = atoi ((char *) strtok (NULL, ": "));
  181.         if (i == 0)
  182.             error ("invalid value for chord_size");
  183.         else
  184.             chord_size = i;
  185.         set_chord_font ();
  186.     }
  187.     else if (!strcmp (command, "textsize") || !strcmp (command, "ts")) {
  188.         i = atoi ((char *) strtok (NULL, ": "));
  189.         if (i == 0)
  190.             error ("invalid value for text_size");
  191.         else
  192.             text_size = i;
  193.     }
  194.     else if (!strcmp (command, "comment") || !strcmp (command, "c")) {
  195.         comment = (char *) strtok (NULL, "\0");
  196.         advance (blank_space);
  197.         blank_space = 0;
  198.         advance (text_size);
  199.         text_line[i_text] = '\0';
  200.         use_text_font ();
  201.         printf (".9  setgray\n");
  202.         printf ("%d  setlinewidth\n", text_size);
  203.         printf ("newpath\n");
  204.         printf ("%d %d moveto\n", hpos, vpos + text_size / 2 - 2);
  205.         printf ("(%s) stringwidth rlineto\n", comment);
  206.         printf ("stroke\n");
  207.         printf ("%d %d moveto\n", hpos, vpos);
  208.         printf ("0  setgray\n");
  209.         printf ("1 setlinewidth\n");
  210.         printf ("(%s) show\n", comment);
  211.         i_text = 0;
  212.     }
  213.     else if (!strcmp (command, "new_song") || !strcmp (command, "ns")) {
  214.         do_new_song ();
  215.     }
  216.     else if (!strcmp (command, "title") || !strcmp (command, "t")) {
  217.         do_title ();
  218.     }
  219.     else if (!strcmp (command, "subtitle") || !strcmp (command, "st")) {
  220.         do_subtitle ();
  221.     }
  222.     else if (!strcmp (command, "define") || !strcmp (command, "d")) {
  223.         do_define_chord ();
  224.     }
  225.     else {
  226.         sprintf (mesg, "Invalid Directive : [%s]", command);
  227.         error (mesg);
  228.         has_directive = FALSE;
  229.     }
  230. }
  231.  
  232. /* --------------------------------------------------------------------------------*/
  233. do_chorus_line () {
  234.     printf ("1  setlinewidth\n");
  235.     printf ("newpath\n");
  236.     printf ("%d %d moveto\n", L_MARGIN - 10, start_of_chorus);
  237.     printf ("0 %d rlineto\n", -(start_of_chorus - end_of_chorus));
  238.     printf ("closepath\n");
  239.     printf ("stroke\n");
  240. }
  241.  
  242. /* --------------------------------------------------------------------------------*/
  243. do_translate(float vert, float horiz) {
  244.     printf ("%f %f translate\n", vert , horiz );
  245.     debug ("changing translation");
  246. }
  247.  
  248. /* --------------------------------------------------------------------------------*/
  249. do_new_song () {
  250.     do_end_of_song ();
  251.     nb_chord = first_ptr = 0;
  252.     song_pages = 0;
  253.     do_start_of_page ();
  254.     init_known_chords ();
  255.     read_chordrc ();
  256. }
  257.  
  258. /* --------------------------------------------------------------------------------*/
  259. init_ps () {
  260.     printf ("%%!PS-Adobe-1.0\n");
  261.     printf ("%%%%Title: A song\n");
  262.     printf ("%%%%Creator: Martin Leclerc & Mario Dorion\n");
  263.     printf ("%%%%Pages: (atend)\n");
  264.     printf ("%%%%BoundingBox: 5 5 605 787\n");
  265.     printf ("%%%%EndComments\n");
  266.     printf ("/inch {72 mul } def\n");
  267.  
  268.     print_re_encode ();
  269.     set_chord_font ();
  270.     set_text_font (text_size);
  271.     do_init_grid_ps ();
  272.     init_known_chords ();
  273.  
  274.     printf ("%%%%EndProlog\n");
  275.  
  276.     printf ("%%%%Page: \"%d\" %d\n", n_pages, n_pages);
  277.     printf ("%%%%BeginPageSetup\n");
  278.     printf ("/pgsave save def\n");
  279.     printf ("%f %f scale\n", scale, scale);
  280.     printf ("%f rotate\n", rotation);
  281.     printf ("%%%%EndPageSetup\n");
  282.  
  283.     vpos = TOP;
  284.     hpos = L_MARGIN;
  285.     if (pagination == 4)
  286.         do_translate (0.0, 800.0);
  287.     else if (pagination == 2)
  288.         do_translate (-40.0, -800.0);
  289.  
  290. }
  291.  
  292. /* --------------------------------------------------------------------------------*/
  293. do_end_of_song() {
  294.     draw_chords();
  295.     do_end_of_page();
  296. }
  297.  
  298. /* --------------------------------------------------------------------------------*/
  299. do_end_of_phys_page () {
  300.     debug ("end_of_phys_page");
  301.     printf ("pgsave restore\n");
  302.     printf ("showpage\n");
  303.     printf ("%%%%EndPage: \"%d\" %d\n", n_pages, n_pages);
  304. }
  305.  
  306. /* --------------------------------------------------------------------------------*/
  307. do_end_of_page () {
  308.     printf ("1  setlinewidth\n");
  309.     printf ("0  setgray\n");
  310.     printf ("newpath\n");
  311.     printf ("%d %d 10 sub moveto\n", L_MARGIN, BOTTOM);
  312.     printf ("%d 0 rlineto\n", WIDTH - L_MARGIN * 2);
  313.     printf ("stroke\n");
  314.     if (number_all || song_pages > 1) {
  315.         int pnum = (number_all ? page_label : song_pages);
  316.         set_text_font (text_size - 2);
  317.         use_text_font ();
  318.         if (page_label % 2 == left_foot_odd) {  /* left side */
  319.             printf ("1 inch %d 3 div moveto\n", BOTTOM);
  320.             printf ("(Page %d) show\n", pnum);
  321.         }
  322.         else {                  /* right side */
  323.             printf ("(Page %d) dup stringwidth pop\n", pnum);
  324.             printf ("%d exch sub 1 inch sub %d 3 div moveto\n",
  325.                     WIDTH, BOTTOM);
  326.             printf ("show\n");
  327.         } if (title1_found) {
  328.             printf ("(%s) dup stringwidth pop 2 div\n", title1);
  329.             printf ("%d 2 div exch sub %d 3 div moveto\n",
  330.                     WIDTH, BOTTOM);
  331.             printf ("show\n");
  332.         } set_text_font (text_size);
  333.     } if (in_chorus) {
  334.         end_of_chorus = vpos;
  335.         do_chorus_line ();
  336.     } if (v_pages == pagination) {
  337.         do_end_of_phys_page ();
  338.         v_pages = 0;
  339.     }
  340. }
  341.  
  342. /* --------------------------------------------------------------------------------*/
  343. do_start_of_page () {
  344.     v_pages++;
  345.     page_label++;
  346.  
  347.     if (v_pages == 1) {
  348.         n_pages++;
  349.         printf ("%%%%Page: \"%d\" %d\n", n_pages, n_pages);
  350.         printf ("%%%%BeginPageSetup\n");
  351.         printf ("/pgsave save def\n");
  352.         printf ("%f %f scale\n", scale, scale);
  353.         printf ("%f rotate\n", rotation);
  354.         printf ("%%%%EndPageSetup\n");
  355.     } if (pagination == 4) {
  356.         if (v_pages == 1)
  357.             do_translate (0.0, 800.0);
  358.         else if (v_pages == 2)
  359.             do_translate (600.0, 0.0);
  360.         else if (v_pages == 3)
  361.             do_translate (-600.0, -800.0);
  362.         else if (v_pages == 4)
  363.             do_translate (600.0, 0.0);
  364.     } if (pagination == 2) {
  365.         if (v_pages == 1)
  366.             do_translate (-40.0, -800.0);
  367.         else if (v_pages == 2)
  368.             do_translate (500.0, 0.0);
  369.     } vpos = TOP;
  370.     hpos = L_MARGIN;
  371.     song_pages++;
  372.     if (in_chorus) {
  373.         start_of_chorus = vpos;
  374.     }
  375. }
  376.  
  377. /* --------------------------------------------------------------------------------*/
  378. advance (int amount) {
  379.     vpos = vpos - amount;       /* Affect text positionning ! */
  380.     if (vpos < BOTTOM) {
  381.         do_end_of_page ();
  382.         do_start_of_page ();
  383.     }
  384. }
  385.  
  386. /* --------------------------------------------------------------------------------*/
  387. print_text_line () {
  388.     int i;
  389.  
  390.     text_line[i_text] = '\0';
  391.  
  392.     for (i = 0; text_line[i] == ' '; i++);
  393.  
  394.     if (!(lyrics_only || auto_space && !has_chord)) {
  395.         advance (blank_space);
  396.         blank_space = 0;
  397.         advance (chord_size + 1);
  398.  
  399.         if ((text_line[i] != '\0')
  400.             && (vpos - text_size <= BOTTOM))
  401.             advance (text_size);
  402.  
  403.         if (need_soc) {
  404.             start_of_chorus = vpos + chord_size;
  405.             need_soc = FALSE;
  406.         } print_chord_line ();
  407.     } if (text_line[i] == '\0') {
  408.         blank_space += text_size - 2;
  409.         debug ("blank line found ");
  410.     }
  411.     else {
  412.         advance (blank_space);
  413.         blank_space = 0;
  414.         advance (text_size - 1);
  415.         if (need_soc) {
  416.             start_of_chorus = vpos + text_size;
  417.             need_soc = FALSE;
  418.         } use_text_font ();
  419.         printf ("%d %d moveto\n", hpos, vpos);
  420.         printf ("(%s) show\n", text_line);
  421.     } i_text = 0;
  422.     i_text_ov = FALSE;
  423.     hpos = L_MARGIN;
  424.     has_chord = FALSE;
  425. }
  426.  
  427. /* --------------------------------------------------------------------------------*/
  428. do_title () {
  429.     char *buf;
  430.     buf = (char *) strtok (NULL, "\0");
  431.     set_text_font (text_size + 5);
  432.     use_text_font ();
  433.     printf ("(%s) dup stringwidth pop 2 div\n", buf);
  434.     printf ("%d 2 div exch sub %d moveto\n", WIDTH, vpos);
  435.     printf ("show\n");
  436.     vpos = vpos - text_size - 5;
  437.     strcpy (title1, buf);
  438.     title1_found = TRUE;
  439.     set_text_font (text_size);
  440.     if (toc_file && song_pages == 1) {  /* generate index entry *//* careful to ignore any \ which may have been inserted */
  441.         char *bp;
  442.         for (bp = buf; *bp; bp++)
  443.             if (*bp != '\\')
  444.                 putc (*bp, toc_file);
  445.         fprintf (toc_file, " ... %d\n", page_label);
  446.     }
  447. }
  448.  
  449. /* --------------------------------------------------------------------------------*/
  450. do_subtitle() {
  451.     char *buf;
  452.     buf = (char *)strtok(NULL, "\0");
  453.     use_text_font();
  454.     printf ("(%s) dup stringwidth pop 2 div\n", buf);
  455.     printf ("%d 2 div exch sub %d moveto\n", WIDTH , vpos);
  456.     printf ("show\n");
  457.     vpos = vpos - text_size ;
  458. }
  459.  
  460. /* --------------------------------------------------------------------------------*/
  461. put_in_string ( unsigned char array[MAXLINE], int *p_index, unsigned char c,
  462.                 int max_index, int *p_ov_flag) {
  463.     if (*p_index < max_index) {
  464.         if ((int) c < 128) {
  465.             array[(*p_index)++] = c;
  466.         }
  467.         else {
  468.             array[(*p_index)++] = '\\';
  469.             sprintf ((char *) &array[*p_index], "%o", c);
  470.             (*p_index) += 3;
  471.         }
  472.     }
  473.     else {
  474.         if (!*p_ov_flag) {
  475.             error ("Buffer Overflow");
  476.             *p_ov_flag = TRUE;
  477.         }
  478.     }
  479. }
  480.  
  481. /* --------------------------------------------------------------------------------*/
  482. process_file (FILE * source_fd) {
  483.     debug ("start of process_file");
  484.  
  485.     n_lines = 0;
  486.  
  487.     while ((c = getc (source_fd)) != EOF) {
  488.         i_input++;
  489.         switch ((char) c) {
  490.  
  491.         case '[':
  492.             if (in_chord)
  493.                 error ("Opening a chord within a chord!");
  494.             else
  495.                 in_chord = TRUE;
  496.             i_chord = 0;
  497.             break;
  498.  
  499.         case ']':
  500.             if (in_chord) {
  501.                 in_chord = FALSE;
  502.                 chord[i_chord] = '\0';
  503.                 do_chord (i_text, chord);
  504.                 has_chord = TRUE;
  505.                 i_chord = 0;
  506.                 i_chord_ov = FALSE;
  507.             }
  508.             else
  509.                 error ("']' found with no matching '['");
  510.             break;
  511.  
  512.         case '{':
  513.             in_directive = TRUE;
  514.             i_directive = 0;
  515.             has_directive = TRUE;
  516.             break;
  517.  
  518.         case '}':
  519.             if (in_directive) {
  520.                 in_directive = FALSE;
  521.                 directive[i_directive] = '\0';
  522.                 for (; (c = getc (source_fd)) != '\n';);
  523.                 i_input = 0;
  524.                 do_directive (directive);
  525.                 has_directive = FALSE;
  526.                 n_lines++;
  527.                 i_directive = 0;
  528.                 i_directive_ov = FALSE;
  529.             }
  530.             else
  531.                 error ("'}' found with no matching '{'");
  532.             break;
  533.  
  534.         case '\n':
  535.             if (in_directive)
  536.                 error ("Line ends while in a directive !");
  537.             if (in_chord)
  538.                 error ("Line ends while in a chord !");
  539.             if (has_directive == FALSE) {
  540.                 if (in_chordrc)
  541.                     error ("line is NOT a directive");
  542.                 else {
  543.                     print_text_line ();
  544.                 }
  545.             }
  546.             else
  547.                 has_directive = FALSE;
  548.             n_lines++;
  549.             i_input = 0;
  550.             in_directive = FALSE;
  551.             in_chord = FALSE;
  552.             break;
  553.  
  554.         case '(':
  555.         case ')':
  556.             if (in_directive) {
  557.                 put_in_string (directive, &i_directive, '\\', MAXTOKEN, &i_directive_ov);
  558.                 put_in_string (directive, &i_directive, c, MAXTOKEN, &i_directive_ov);
  559.                 break;
  560.             }
  561.             else if (in_chord) {        /* allow parens in chord names */
  562.                 put_in_string (chord, &i_chord, '\\', MAXLINE, &i_text_ov);
  563.                 put_in_string (chord, &i_chord, c, MAXLINE, &i_text_ov);
  564.                 break;
  565.             }
  566.             else {
  567.                 put_in_string (text_line, &i_text, '\\', MAXLINE, &i_text_ov);
  568.                 put_in_string (text_line, &i_text, c, MAXLINE, &i_text_ov);
  569.                 break;
  570.         } /* This case HAS to be the last before the default statement !!! */ case '#':
  571.             if (i_input == 1) {
  572.                 for (; (c = getc (source_fd)) != '\n';);
  573.                 n_lines++;
  574.                 i_input = 0;
  575.                 break;
  576.         } default:
  577.             if (in_chord) {
  578.                 if (c != ' ')
  579.                     put_in_string (chord, &i_chord, c, MAXTOKEN, &i_text_ov);
  580.             }
  581.             else if (in_directive) {
  582.                 put_in_string (directive, &i_directive, c, MAXTOKEN, &i_directive_ov);
  583.             }
  584.             else {
  585.                 put_in_string (text_line, &i_text, c, MAXLINE, &i_text_ov);
  586.             } break;
  587.         }
  588.     } print_text_line ();
  589. }
  590.  
  591. /* --------------------------------------------------------------------------------*/
  592. read_input_file () {
  593.     current_file = source;
  594.     source_fd = fopen (source, "r");
  595.     if (source_fd == NULL) {
  596.         fprintf (stderr, "Unable to open [%s]\n", source);
  597.         exit (1);
  598.     } process_file (source_fd);
  599.     fclose (source_fd);
  600. }
  601.  
  602. /* --------------------------------------------------------------------------------*/
  603. read_chordrc () {
  604.     char chordrc[MAXTOKEN];
  605.     FILE *chordrc_fd;
  606.     int n_lines_save;
  607.  
  608.     strcpy (chordrc, "s:.chordrc");
  609.     current_file = chordrc;
  610.     chordrc_fd = fopen (chordrc, "r");
  611.     if (chordrc_fd != NULL) {
  612.         n_lines_save = n_lines;
  613.         n_lines = 1;
  614.         in_chordrc = TRUE;
  615.         process_file (chordrc_fd);
  616.         in_chordrc = FALSE;
  617.         n_lines = n_lines_save;
  618.         fclose (chordrc_fd);
  619.     } current_file = source;
  620. }
  621.  
  622. /* --------------------------------------------------------------------------------*/
  623. debug(char *dbg_str) {
  624.     if (debug_mode)
  625.         fprintf (stderr, "Debug: %s\n", dbg_str);
  626. }
  627.  
  628. /* --------------------------------------------------------------------------------*/
  629. print_version() {
  630.     char *version = VERSION;
  631.     char *patch_level = PATCH_LEVEL;
  632.         
  633.     printf ("chord version %s, patchlevel %s\n", version, patch_level);
  634. }
  635. /* --------------------------------------------------------------------------------*/
  636. error(char *err_str) {
  637.     fprintf(stderr, "WARNING: %s\n",err_str);
  638.     fprintf(stderr, "         in file %s, line %d\n", current_file,n_lines);
  639. }
  640.  
  641. /* --------------------------------------------------------------------------------*/
  642. main (int argc, char **argv)
  643. {
  644.     int c, i;
  645.  
  646.     while ((c = getopt (argc, argv, "hlDd24Vc:t:g:C:T:x:aLRp:i:")) != -1)
  647.         switch (c) {
  648.  
  649.         case 'h':
  650.             do_help (argv[0]);
  651.             exit (1);
  652.             break;
  653.  
  654.         case 'D':
  655.             debug_mode = TRUE;
  656.             break;
  657.  
  658.         case 'd':
  659.             init_known_chords ();
  660.             dump_chords ();
  661.             exit (0);
  662.  
  663.         case 'c':
  664.             i = atoi (optarg);
  665.             if (i == 0)
  666.                 error ("invalid value for chord_size");
  667.             else
  668.                 chord_size = i;
  669.             break;
  670.  
  671.         case 't':
  672.             i = atoi (optarg);
  673.             if (i == 0)
  674.                 error ("invalid value for text_size");
  675.             else
  676.                 text_size = i;
  677.             break;
  678.  
  679.         case 'x':
  680.             i = atoi (optarg);
  681.             if (i == 0)
  682.                 error ("invalid value for transposition");
  683.             else
  684.                 transpose = i;
  685.             break;
  686.  
  687.         case 'T':
  688.             text_font = optarg;
  689.             break;
  690.  
  691.         case 'C':
  692.             chord_font = optarg;
  693.             break;
  694.  
  695.         case 'g':
  696.             i = atoi (optarg);
  697.             if (i == 0)
  698.                 error ("invalid value for grid_size");
  699.             else
  700.                 grid_size = i;
  701.             break;
  702.  
  703.         case 'l':
  704.             lyrics_only = TRUE;
  705.             break;
  706.  
  707.         case 'V':
  708.             print_version ();
  709.             exit (0);
  710.  
  711.         case '2':
  712.             pagination = 2;
  713.             scale = scale2;
  714.             rotation = 90.0;
  715.             break;
  716.  
  717.         case '4':
  718.             pagination = 4;
  719.             scale = scale4;
  720.             break;
  721.  
  722.         case 'i':
  723.             if (!strcmp (optarg, "-"))
  724.                 toc_file = stderr;
  725.             else
  726.                 toc_file = fopen (optarg, "w");
  727.             if (toc_file == NULL) {
  728.                 perror (optarg);
  729.                 error ("unable to create index file");
  730.             } break;
  731.  
  732.         case 'a':
  733.             auto_space = TRUE;
  734.             break;
  735.  
  736.         case 'p':
  737.             page_label = atoi (optarg);
  738.             number_all = TRUE;
  739.             break;
  740.  
  741.         case 'L':
  742.             left_foot_odd = 1;
  743.             break;
  744.  
  745.         case 'R':
  746.             left_foot_odd = 0;
  747.             break;
  748.  
  749.         case '?':
  750.             do_help (argv[0]);
  751.             break;
  752.         } /* File Processing */ init_ps ();
  753.  
  754.     read_chordrc ();
  755.  
  756.     chord_inc = chord_size * 1.5;
  757.  
  758.     if (optind == argc) {
  759.         debug ("Reading stdin");
  760.         strcpy (source, "stdin");
  761.         process_file (stdin);
  762.     }
  763.     else {
  764.         for (; optind < argc; optind++) {
  765.             debug ("Processing a file");
  766.             strcpy (source, argv[optind]);
  767.             read_input_file ();
  768.             if (optind < argc - 1)
  769.                 do_new_song ();
  770.         }
  771.     } do_end_of_song ();
  772.     if (v_pages != 0) {
  773.         do_end_of_phys_page ();
  774.     } printf ("%%%%Trailer\n");
  775.     printf ("%%%%Pages: %d 1\n", n_pages);
  776.     printf ("%%%%EOF\n");
  777.     if (toc_file)
  778.         fclose (toc_file);
  779.     exit (0);
  780.     return (0);
  781. }
  782.